import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { makeSelectUser } from "services/Auth/selectors";
import { makeSelectClient } from "services/global/selectors";
import { rtsRequest } from "services/rts/actions";
import { authLogout } from "services/Auth/actions";
import { authClient } from "services/global/actions";
import { push, goBack, replace } from "react-router-redux";
import uuid from "uuid";
import { message, Spin } from "antd";
// 中文化moment
import Moment from "../../components/Moment";

// 全局css
import "./style.scss";
// 图标字体必要css
import "./font_icon/iconfont.css";

import modules from "../../pages/modules";
import BasicLayout from "./Layout/BasicLayout";
import PowerConfig from "../../common/power";

const isMobile = /(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent);
// 根据配置读取并拼接组件
const BaseConstructor = (config, title) => {
  class Base extends React.Component {
    static propTypes = {
      user: React.PropTypes.object
    };

    static defaultProps = {
      user: null
    };

    constructor(props) {
      super(props);
      this.state = this.getInitialState();
    }

    componentWillReceiveProps(nextProps) {
      if (this.ifErr(this.props, nextProps)) {
        let error = nextProps.error;
        message.error(error[error.length - 1]);
      }
    }

    getParameterByName = (name, url) => {
      if (!url) url = window.location.href;
      name = name.replace(/[\[\]]/g, "\\$&");
      var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
      if (!results) return null;
      if (!results[2]) return "";
      return decodeURIComponent(results[2].replace(/\+/g, " "));
    };

    ifErr(props, nProps) {
      if (!props.error && nProps.error) {
        return true;
      } else if (
        props.error &&
        nProps.error &&
        props.errLen !== nProps.errLen
      ) {
        return true;
      } else {
        return false;
      }
    }

    // 根据config配置初始化base的state
    getInitialState = () => {
      let initialState = Object.assign(config.initialState, {
        dataUUID: uuid.v1()
      });
      config["component"].map(item => {
        Object.assign(initialState, item.setState);
      });
      return initialState;
    };

    // 根据config配置传入base中state或props中对应属性到组件的props中
    setConfigProps = index => {
      let extraProps = {};
      config["component"][index].getState &&
        config["component"][index].getState.map(item => {
          extraProps[item] = this.state[item];
        });
      config["component"][index].getProps &&
        config["component"][index].getProps.map(item => {
          extraProps[item] = this.props[item];
        });
      config["component"][index].getMethodToProps &&
        config["component"][index].getMethodToProps.map(item => {
          extraProps[item] = this[item];
        });
      return extraProps;
    };

    // 传递到子组件中的修改父组件state的方法
    changeBaseState = newState => {
      this.setState(newState);
    };

    render() {
      const { spin } = this.props;
      const role =
        (this.props.user &&
          this.props.user.roles &&
          this.props.user.roles[0]) ||
        "";
      const authority = PowerConfig[role] || {};
      let innerComponents = [];
      let openKey = config.initialState.openKeys;
      openKey = openKey
        .toLowerCase()
        .replace(/( |^)[a-z]/g, L => L.toUpperCase());

      if (authority[openKey] || true) {
        for (let i = 0; i < config.component.length; i++) {
          innerComponents.push(modules[config.component[i].module]);
        }
      } else {
        innerComponents.push(modules["Exception"]);
      }
      return (
        <BasicLayout
          pageStyle={config.pageStyle}
          contents={innerComponents.map((item, index) => {
            return React.createElement(
              item,
              Object.assign(
                {},
                {
                  key: index,
                  user: this.props.user,
                  to: this.props.to,
                  match: this.props.match,
                  info: config["component"][index]["info"],
                  changeBaseState: this.changeBaseState,
                  subTitle: this.state.subTitle,
                  isMobile
                },
                this.setConfigProps(index)
              )
            );
          })}
          spin={this.props.spin}
          replace={this.props.replace}
          match={this.props.match}
          user={this.props.user}
          logout={this.props.logout}
          title={this.state.title}
          to={this.props.to}
          goBack={this.props.goBack}
          rts={this.props.rts}
          changeBaseState={this.changeBaseState}
          selectedKeys={this.state.selectedKeys}
          openKeys={this.state.openKeys}
          subTitle={this.state.subTitle}
        />
      );
    }
  }

  const mapDispatchToProps = dispatch => {
    return {
      dispatch,
      to: path => dispatch(push(path)),
      goBack: () => dispatch(goBack()),
      replace: (path, search) => dispatch(replace({ pathname: path, search })),
      getMe: token => dispatch(authClient(token)),
      logout: () => dispatch(authLogout()),
      rts: (filter, uuid, field, cb, noSpin) =>
        dispatch(rtsRequest(filter, uuid, field, cb, noSpin))
    };
  };

  const error = state => state.get("rts").get("error");
  const spin = state => state.get("rts").get("spin");
  const errLen = state => state.get("rts").get("errLen");

  const mapStateToProps = createStructuredSelector({
    user: makeSelectUser(),
    client: makeSelectClient(),
    error,
    spin,
    errLen
  });

  return connect(mapStateToProps, mapDispatchToProps)(Base);
};

export default BaseConstructor;
